// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

suite("nereids_scalar_fn_A") {
	sql 'use regression_test_nereids_function_p0'
	sql 'set enable_nereids_planner=true'
	sql 'set enable_fallback_to_original_planner=false'
	qt_sql_abs_Double "select abs(kdbl) from fn_test order by kdbl"
	qt_sql_abs_Double_notnull "select abs(kdbl) from fn_test_not_nullable order by kdbl"
	qt_sql_abs_Float "select abs(kfloat) from fn_test order by kfloat"
	qt_sql_abs_Float_notnull "select abs(kfloat) from fn_test_not_nullable order by kfloat"
	qt_sql_abs_LargeInt "select abs(klint) from fn_test order by klint"
	qt_sql_abs_LargeInt_notnull "select abs(klint) from fn_test_not_nullable order by klint"
	qt_sql_abs_BigInt "select abs(kbint) from fn_test order by kbint"
	qt_sql_abs_BigInt_notnull "select abs(kbint) from fn_test_not_nullable order by kbint"
	qt_sql_abs_SmallInt "select abs(ksint) from fn_test order by ksint"
	qt_sql_abs_SmallInt_notnull "select abs(ksint) from fn_test_not_nullable order by ksint"
	qt_sql_abs_Integer "select abs(kint) from fn_test order by kint"
	qt_sql_abs_Integer_notnull "select abs(kint) from fn_test_not_nullable order by kint"
	qt_sql_abs_TinyInt "select abs(ktint) from fn_test order by ktint"
	qt_sql_abs_TinyInt_notnull "select abs(ktint) from fn_test_not_nullable order by ktint"
	qt_sql_abs_DecimalV2 "select abs(kdcmls1) from fn_test order by kdcmls1"
	qt_sql_abs_DecimalV2_notnull "select abs(kdcmls1) from fn_test_not_nullable order by kdcmls1"
	qt_sql_acos_Double "select acos(kdbl) from fn_test order by kdbl"
	qt_sql_acos_Double_notnull "select acos(kdbl) from fn_test_not_nullable order by kdbl"
    qt_sql_acos_Double_NAN "select acos(cast(1.1 as double))"
	qt_sql_acos_Double_NULL "select acos(null)"
	sql "select aes_decrypt(kvchrs1, kvchrs1) from fn_test order by kvchrs1, kvchrs1"
	sql "select aes_decrypt(kvchrs1, kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1"
	sql "select aes_decrypt(kstr, kstr) from fn_test order by kstr, kstr"
	sql "select aes_decrypt(kstr, kstr) from fn_test_not_nullable order by kstr, kstr"
	sql "select aes_decrypt(kvchrs1, kvchrs1, kvchrs1) from fn_test order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_decrypt(kvchrs1, kvchrs1, kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_decrypt(kstr, kstr, kstr) from fn_test order by kstr, kstr, kstr"
	sql "select aes_decrypt(kstr, kstr, kstr) from fn_test_not_nullable order by kstr, kstr, kstr"
	sql "select aes_decrypt(kvchrs1, kvchrs1, kvchrs1, 'AES_128_ECB') from fn_test order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_decrypt(kvchrs1, kvchrs1, kvchrs1, 'AES_128_ECB') from fn_test_not_nullable order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_decrypt(kstr, kstr, kstr, 'AES_128_ECB') from fn_test order by kstr, kstr, kstr, kstr"
	sql "select aes_decrypt(kstr, kstr, kstr, 'AES_128_ECB') from fn_test_not_nullable order by kstr, kstr, kstr, kstr"
	sql "select aes_encrypt(kvchrs1, kvchrs1) from fn_test order by kvchrs1, kvchrs1"
	sql "select aes_encrypt(kvchrs1, kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1"
	sql "select aes_encrypt(kstr, kstr) from fn_test order by kstr, kstr"
	sql "select aes_encrypt(kstr, kstr) from fn_test_not_nullable order by kstr, kstr"
	sql "select aes_encrypt(kvchrs1, kvchrs1, kvchrs1) from fn_test order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_encrypt(kvchrs1, kvchrs1, kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_encrypt(kstr, kstr, kstr) from fn_test order by kstr, kstr, kstr"
	sql "select aes_encrypt(kstr, kstr, kstr) from fn_test_not_nullable order by kstr, kstr, kstr"
	sql "select aes_encrypt(kvchrs1, kvchrs1, kvchrs1, 'AES_128_ECB') from fn_test order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_encrypt(kvchrs1, kvchrs1, kvchrs1, 'AES_128_ECB') from fn_test_not_nullable order by kvchrs1, kvchrs1, kvchrs1"
	sql "select aes_encrypt(kstr, kstr, kstr, 'AES_128_ECB') from fn_test order by kstr, kstr, kstr, kstr"
	sql "select aes_encrypt(kstr, kstr, kstr, 'AES_128_ECB') from fn_test_not_nullable order by kstr, kstr, kstr, kstr"
	qt_sql_append_trailing_char_if_absent_Varchar_Varchar "select append_trailing_char_if_absent(kvchrs1, kvchrs1) from fn_test order by kvchrs1, kvchrs1"
	qt_sql_append_trailing_char_if_absent_Varchar_Varchar_notnull "select append_trailing_char_if_absent(kvchrs1, kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1"
	qt_sql_append_trailing_char_if_absent_String_String "select append_trailing_char_if_absent(kstr, kstr) from fn_test order by kstr, kstr"
	qt_sql_append_trailing_char_if_absent_String_String_notnull "select append_trailing_char_if_absent(kstr, kstr) from fn_test_not_nullable order by kstr, kstr"
	qt_sql_ascii_Varchar "select ascii(kvchrs1) from fn_test order by kvchrs1"
	qt_sql_ascii_Varchar_notnull "select ascii(kvchrs1) from fn_test_not_nullable order by kvchrs1"
	qt_sql_ascii_String "select ascii(kstr) from fn_test order by kstr"
	qt_sql_ascii_String_notnull "select ascii(kstr) from fn_test_not_nullable order by kstr"
	qt_sql_asin_Double "select asin(kdbl) from fn_test order by kdbl"
	qt_sql_asin_Double_notnull "select asin(kdbl) from fn_test_not_nullable order by kdbl"
	qt_sql_atan_Double "select atan(kdbl) from fn_test order by kdbl"
	qt_sql_atan_Double_notnull "select atan(kdbl) from fn_test_not_nullable order by kdbl"
	qt_sql_atan2_Double "select atan2(kdbl, kdbl*kdbl) from fn_test order by kdbl"
	qt_sql_atan2_Double_notnull "select atan2(kdbl, kdbl*kdbl) from fn_test_not_nullable order by kdbl"
	qt_sql_auto_partition_name_list_column_type_mixed "select auto_partition_name('list', kchrs1, kbool) from fn_test_not_nullable where id < 3 order by kchrs1"
	qt_sql_auto_partition_name_list_column_literal_mixed "select auto_partition_name('list', kstr, 'hello') from fn_test_not_nullable where id < 3 order by kstr"
	qt_sql_auto_partition_name_list_column "select auto_partition_name('list', kchrs1, kvchrs1) from fn_test_not_nullable where id < 3 order by kchrs1"
	qt_sql_auto_partition_name_list_column "select auto_partition_name('list', kchrs1, null, kvchrs1) from fn_test where id < 3 order by kchrs1"
	qt_sql_auto_partition_name_list_column "select auto_partition_name('list', null, kstr, null, null) from fn_test where id < 3 order by kstr"
	qt_sql_auto_partition_name_list_literal_empty "select auto_partition_name('list', '')"
	qt_sql_auto_partition_name_list_literal_mixed "select auto_partition_name('list', '你好', true, false)"
	qt_sql_auto_partition_name_list_literal_mixed "select auto_partition_name('list', '-hello')"
	qt_sql_auto_partition_name_list_literal_mixed "select auto_partition_name('list', '@#￥%~|world11111....')"
	qt_sql_auto_partition_name_list_literal_mixed "select auto_partition_name('list', 'list', null, true, null)"
	qt_sql_auto_partition_name_list_literal_mixed "select auto_partition_name('list', '你好 hello!@#￥%~|world11111.... 世界');"
	qt_sql_auto_partition_name_list_literal_mixed "select auto_partition_name('list', 'this_is_a_very_long_tenant_group_name_that_will_cause_partition_name_to_exceed_fifty_characters');"

	qt_sql_auto_partition_name_list_literal_null "select auto_partition_name('list', null, null, null);"
	qt_sql_auto_partition_name_range_literal_notnull "select auto_partition_name('range', 'day', '2022-12-12 19:20:30')"
	qt_sql_auto_partition_name_range_literal_notnull "select auto_partition_name('range', 'month', '2022-12-12 19:20:30')"
	qt_sql_auto_partition_name_range_literal_notnull "select auto_partition_name('range', 'year', '2022-12-12 19:20:30')"
	qt_sql_auto_partition_name_range_literal_notnull "select auto_partition_name('range', 'hour', '2022-12-12 19:20:30')"
	qt_sql_auto_partition_name_range_literal_notnull "select auto_partition_name('range', 'minute', '2022-12-12 19:20:30')"
	qt_sql_auto_partition_name_range_literal_notnull "select auto_partition_name('range', 'second', '2022-12-12 19:20:30')"
	qt_sql_auto_partition_name_range_notnull "select auto_partition_name('range', 'day', kdt) from fn_test_not_nullable order by kdt"
	qt_sql_auto_partition_name_range_notnull "select auto_partition_name('range', 'month', kdt) from fn_test_not_nullable order by kdt"
	qt_sql_auto_partition_name_range_notnull "select auto_partition_name('range', 'year', kdt) from fn_test_not_nullable order by kdt"
	qt_sql_auto_partition_name_range_notnull "select auto_partition_name('range', 'hour', kdt) from fn_test_not_nullable order by kdt"
	qt_sql_auto_partition_name_range_notnull "select auto_partition_name('range', 'minute', kdt) from fn_test_not_nullable order by kdt"
	qt_sql_auto_partition_name_range_notnull "select auto_partition_name('range', 'second', kdt) from fn_test_not_nullable order by kdt"

	test{
		sql """select auto_partition_name('hello');"""
		exception "function auto_partition_name must contains at least two arguments"
	}
	test{
		sql """select auto_partition_name('range', 'day', '123-12-12 19:20:30', '123-12-12 19:20:30');"""
		exception "range auto_partition_name must contains three arguments"
	}
	test{
		sql """select auto_partition_name(kdt, 'day', kdt) from fn_test_not_nullable order by kdt"""
		exception "auto_partition_name must accept literal for 1st argument"
	}
	test{
		sql """select auto_partition_name('range', kdt, kdt) from fn_test_not_nullable order by kdt"""
		exception "auto_partition_name must accept literal for 2nd argument"
	}
	test{
		sql """select auto_partition_name('range', 'second', '')"""
		exception "The range partition only support DATE|DATETIME"
	}
	test{
		sql """select auto_partition_name('range', 'second', '123-12-12 19:20:30')"""
		exception "The range partition only support DATE|DATETIME"
	}
	test{
		sql """select auto_partition_name('range', 'second', '123-12-12')"""
		exception "The range partition only support DATE|DATETIME"
	}
	test{
		sql """select auto_partition_name('range', 'second', '2011-12-12 123:12:12')"""
		exception "The range partition only support DATE|DATETIME"
	}
	test{
		sql """select auto_partition_name('range', 'day', 1);"""
		exception "The range partition only support DATE|DATETIME"
	}
	test{
		sql """select auto_partition_name('range', 'year', 'hello');"""
		exception "The range partition only support DATE|DATETIME"
	}
	test{
		sql """select auto_partition_name('ranges', 'year', 'hello');"""
		exception "function auto_partition_name must accept range|list for 1st argument"
	}
	test{
		sql """select auto_partition_name('lists', 'year', 'hello');"""
		exception "function auto_partition_name must accept range|list for 1st argument"
	}
	test{
		sql """select auto_partition_name('range', 'years', 'hello');"""
		exception "range auto_partition_name must accept year|month|day|hour|minute|second for 2nd argument"
	}

	sql"""DROP TABLE IF EXISTS test_partition_name_list;"""
    sql"""CREATE TABLE test_partition_name_list (
        id int,
        name varchar(300)
    ) ENGINE=OLAP
    DUPLICATE KEY(id)
    AUTO PARTITION BY LIST (name)()
    DISTRIBUTED BY HASH(id) BUCKETS 1
    PROPERTIES ( 'replication_num' = '1' );"""

    def comparePartitionNameList = { test_msg ->
        sql"""INSERT INTO test_partition_name_list VALUES (1, '${test_msg}');"""
        def tblRes = sql"""SHOW PARTITIONS FROM test_partition_name_list;"""
        def funcRes = sql"""SELECT AUTO_PARTITION_NAME('list', '${test_msg}');"""
        assertEquals(tblRes[0][1], funcRes[0][0], "table partition name: ${tblRes[0][1]} should equal function result: ${funcRes[0][0]}");
        sql"""TRUNCATE TABLE test_partition_name_list;"""
        sql"""ALTER TABLE test_partition_name_list DROP PARTITION ${tblRes[0][1]};"""
    }

    comparePartitionNameList("short_name");
    comparePartitionNameList("短的名字");
    comparePartitionNameList("short_wi th_1234_&%^*")
    comparePartitionNameList("特殊^的短 名字&@!")
    comparePartitionNameList("this_is_a_very_long_tenant_group_name_that_will_cause_partition_name_to_exceed_fifty_characters");
    comparePartitionNameList("世界");
    comparePartitionNameList("Apache Doris 是一款基于 MPP 架构的高性能、实时分析型数据库，它以高效、简单和统一的特性著称，能够在亚秒级的时间内返回海量数据的查询结果。");
    comparePartitionNameList("Apache Dorisは、MPPアーキテクチャに基づく高性能、リアルタイム分析型データベースです。効率的でシンプルであり、統一された特性で知られており、亜秒級の時間で大量データのクエリ結果を返すことができます。")
    comparePartitionNameList("Apache Doris는 MPP 아키텍처를 기반으로 한 고성능, 실시간 분석형 데이터베이스로, 효율적이고 간단하며 일관된 특성으로 유명하며, 얼마 안 되는 시간 안에 대량의 데이터의 쿼리 결과를 반환할 수 있습니다.");
    comparePartitionNameList("你好 hello!@#￥%~|world11111.... 世界");

    sql"""DROP TABLE IF EXISTS test_partition_name_list;"""
}
